#include<iostream>
using namespace std;
#include<pthread.h>
#include<queue>
#define  NUM 5
template<class T>
class ThreadPool
{
  private:
    queue<T> task_queue;
    int thread_num;
    pthread_mutex_t lock;
    pthread_cond_t cond;
  public:
    ThreadPool(int num=NUM)
      :thread_num(num)
    {
      pthread_mutex_init(&lock,NULL);
      pthread_cond_init(&cond,NULL);
    }
    void LockQueue()
    {
      pthread_mutex_lock(&lock);
    }
    void UnlockQueue()
    {
      pthread_mutex_unlock(&lock);
    }
    void waitcond()
    {
      pthread_cond_wait(&cond,&lock);
    }
    void wakeup()
    {
      pthread_cond_signal(&cond);
    }
    bool isEmptyThreadPool()
    {
      return task_queue.size()==0;
    }
    
    static void* Routine(void* arg)
    {
        pthread_detach(pthread_self());
      ThreadPool* This=(ThreadPool*) arg;
      while(true)
      {
        This->LockQueue();
        if(This->isEmptyThreadPool())
        {
         This->waitcond();
        }
        T t;
       This->Pop(t);
        This->UnlockQueue();
        cout<<"thread:"<<pthread_self()<<"run:";
        t.run();
      }
    }
    void Push(T& in)
    {
      LockQueue();
      task_queue.push(in);
      UnlockQueue();
      wakeup();
    }
    void Pop(T& out)
    {
       out=task_queue.front();
       task_queue.pop();
    }
    void InitThreadPool()
    {
      pthread_t tid;
      for(int i=0;i<thread_num;i++)
      {
        pthread_create(&tid,NULL,Routine,this);
      }
    }
    ~ThreadPool()
    {
      pthread_cond_destroy(&cond);
     pthread_mutex_destroy(&lock); 
    }
};
